package cn.hbads.version.parser;

import cn.hbads.version.annotation.FieldVersion;
import cn.hbads.version.annotation.ListVersion;
import cn.hbads.version.annotation.OneToOneVersion;
import cn.hbads.version.domain.version.model.BusinessModel;
import cn.hbads.version.parser.model.FieldVersionModel;
import cn.hbads.version.parser.model.ListVersionModel;
import cn.hbads.version.parser.model.VersionModel;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * <b> 解析BusinessModel上的版本注解 </b>
 *
 * @author : yvvb
 * @date : 2025/5/5
 */
public final class BusinessModelParser {
    protected static final Map<Class<? extends BusinessModel>, Map<String, VersionModel>> PARSE_CLASS_MAP = new ConcurrentHashMap<>();

    @SneakyThrows
    private static void parseVersionModelMap(Map<String, VersionModel> fieldVersionMap, Class<?> parseClazz) {
        final Field[] fields = parseClazz.getDeclaredFields();
        for (Field field : fields) {
            final FieldVersion fieldVersion = field.getAnnotation(FieldVersion.class);
            if (fieldVersion != null) {
                if (fieldVersionMap.containsKey(field.getName())) {
                    throw new RuntimeException("重复的业务参数名称");
                }
                fieldVersionMap.put(field.getName(), FieldVersionModel.buildFrom(field, fieldVersion));
                continue;
            }
            if (List.class.isAssignableFrom(field.getType())) {
                final ListVersion listVersion = field.getAnnotation(ListVersion.class);
                if (listVersion != null) {
                    if (fieldVersionMap.containsKey(field.getName())) {
                        throw new RuntimeException("重复的业务参数名称");
                    }
                    fieldVersionMap.put(field.getName(), ListVersionModel.buildFrom(field, listVersion));
                    continue;
                }
            }
            final OneToOneVersion embeddedField = field.getAnnotation(OneToOneVersion.class);
            if (embeddedField != null) {
                parseVersionModelMap(fieldVersionMap, field.getType());
            }
        }
    }

    public static Map<String, VersionModel> parseIfAbsent(Class<? extends BusinessModel> businessModelClass) {
        return PARSE_CLASS_MAP.computeIfAbsent(businessModelClass, clazz -> {
            Map<String, VersionModel> fieldVersionMap = new HashMap<>();
            parseVersionModelMap(fieldVersionMap, clazz);
            return fieldVersionMap;
        });
    }
}
